/*
 * Copyright 2003-2007 (c) Live Media Pty Ltd. <argot@einet.com.au> 
 *
 * This software is licensed under the Argot Public License 
 * which may be found in the file LICENSE distributed 
 * with this software.
 *
 * More information about this license can be found at
 * http://www.einet.com.au/License
 * 
 * The Developer of this software is Live Media Pty Ltd,
 * PO Box 4591, Melbourne 3001, Australia.  The license is subject 
 * to the law of Victoria, Australia, and subject to exclusive 
 * jurisdiction of the Victorian courts.
 */

package com.colony.concurrent;

import java.util.Stack;

/**
 *  A thread pool.
 */
public class SystemThreadPool
implements ThreadPool, ThreadActivator
{
   protected int _min;   // default 0.
   protected int _max;   // if 0 unlimited.  default 0.
   protected int _threadCount;
   protected Stack _freeThreadPool;
   protected long _timeout;

   private SystemThreadPool()
   {
      _threadCount = 0;
      _freeThreadPool = new Stack();
      _min = 0;
      _max = 0;
      _timeout = 10000;
   }
   
   public int minThreads()
   {
       return _min;
   }

   public void setMinThreads( int m )
   {
      _min = m;       
   } 

   public int maxThreads()
   {
       return _max;
   }

   public void setMaxThreads( int m )
   {
      _max = m;       
   }

   public long threadTimeout()
   {
       return _timeout;
   }

   public void setThreadTimeout( long t )
   {
       _timeout = t;   
   }

   public int threadCount()
   {
       return _threadCount;
   }


   /**
    * This class can only be accessed by the LocalThreadPool class.  This is the global
    * thread pool.  The LocalThreadPool is allowed to actually get the real threads.
    */

   private static ThreadPool _threadPool;

   public static synchronized ThreadPool getThreadPool()
   {
      if ( _threadPool == null )
         _threadPool = new SystemThreadPool();
      return _threadPool;
   }


   public synchronized Worker getThread()
   {
      if ( _freeThreadPool.size() == 0 )
      {
         if ( _threadCount >= _max && _max != 0 )
         {
            return null;  // sorry.. no more threads for you!
         }
         _threadCount++;
         Worker w = new Worker();
         w.setOwner( this, _timeout );
         w.setDaemon( true );
         w.start();
         w.waitStart();
         return w;
      }
      else 
      {
         return (Worker) _freeThreadPool.pop();
      }
   }

   public synchronized void returnThread( Worker w )
   {
      w.setOwner( this, _timeout );
      _freeThreadPool.push( w );
   }

   public synchronized void workerTimeout( Worker w )
   {
      if ( _threadCount > _min )
      {
         _threadCount--;
         _freeThreadPool.remove( w );
         w.stopWorker();
      }
   }

   public boolean assignThread( Runnable worker )
   {
	   	Worker w = getThread();
	   	if ( w != null )
	   	{
	   		w.activate( worker );
	   		return true;
	   	}
	   	return false;
   }

}